@noirmd/previewer 2.1.4 → 2.1.5
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/NReditor.cjs +153 -161
- package/dist/NReditor.cjs.map +1 -1
- package/dist/NReditor.js +153 -161
- package/dist/NReditor.js.map +1 -1
- package/dist/button.css +6 -0
- package/dist/card.css +5 -5
- package/dist/core.cjs +31 -20
- package/dist/core.cjs.map +1 -1
- package/dist/core.d.cts +1 -0
- package/dist/core.d.ts +1 -0
- package/dist/core.js +31 -20
- package/dist/core.js.map +1 -1
- package/dist/hover3d.css +1 -1
- package/dist/index.cjs +151 -159
- package/dist/index.cjs.map +1 -1
- package/dist/index.d.cts +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +151 -159
- package/dist/index.js.map +1 -1
- package/dist/modal.css +7 -1
- package/dist/react.cjs +153 -161
- package/dist/react.cjs.map +1 -1
- package/dist/react.d.cts +1 -0
- package/dist/react.d.ts +1 -0
- package/dist/react.js +153 -161
- package/dist/react.js.map +1 -1
- package/dist/vanilla.cjs +151 -159
- package/dist/vanilla.cjs.map +1 -1
- package/dist/vanilla.d.cts +1 -0
- package/dist/vanilla.d.ts +1 -0
- package/dist/vanilla.js +151 -159
- package/dist/vanilla.js.map +1 -1
- package/dist/vue.cjs +151 -159
- package/dist/vue.cjs.map +1 -1
- package/dist/vue.d.cts +1 -0
- package/dist/vue.d.ts +1 -0
- package/dist/vue.js +151 -159
- package/dist/vue.js.map +1 -1
- package/package.json +1 -1
package/dist/NReditor.cjs
CHANGED
|
@@ -565,6 +565,22 @@ function parseHtmlAttrs(attrsString) {
|
|
|
565
565
|
}
|
|
566
566
|
|
|
567
567
|
// core/parser.ts
|
|
568
|
+
var VOID_ELEMENTS = /* @__PURE__ */ new Set([
|
|
569
|
+
"area",
|
|
570
|
+
"base",
|
|
571
|
+
"br",
|
|
572
|
+
"col",
|
|
573
|
+
"embed",
|
|
574
|
+
"hr",
|
|
575
|
+
"img",
|
|
576
|
+
"input",
|
|
577
|
+
"link",
|
|
578
|
+
"meta",
|
|
579
|
+
"param",
|
|
580
|
+
"source",
|
|
581
|
+
"track",
|
|
582
|
+
"wbr"
|
|
583
|
+
]);
|
|
568
584
|
function parseMarkdown(markdown2) {
|
|
569
585
|
if (!markdown2) return [];
|
|
570
586
|
const lines = markdown2.replace(/\r\n/g, "\n").replace(/\r/g, "").split("\n");
|
|
@@ -578,8 +594,19 @@ function parseMarkdown(markdown2) {
|
|
|
578
594
|
if (match = trimmed.match(/^(#{1,6})\s+(.+)$/)) {
|
|
579
595
|
const level = match[1].length;
|
|
580
596
|
const rawText = match[2];
|
|
581
|
-
const { text:
|
|
582
|
-
|
|
597
|
+
const { text: rawParsedText, classes: classes2, id: customId } = extractAttributes(rawText);
|
|
598
|
+
let text2 = rawParsedText;
|
|
599
|
+
let align;
|
|
600
|
+
const alignCenter = text2.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
601
|
+
const alignRight = text2.match(/^->\s*(.+?)\s*->\s*$/);
|
|
602
|
+
if (alignCenter) {
|
|
603
|
+
text2 = alignCenter[1];
|
|
604
|
+
align = "center";
|
|
605
|
+
} else if (alignRight) {
|
|
606
|
+
text2 = alignRight[1];
|
|
607
|
+
align = "right";
|
|
608
|
+
}
|
|
609
|
+
const baseId = customId || generateId(text2);
|
|
583
610
|
let id2 = baseId;
|
|
584
611
|
let n = 1;
|
|
585
612
|
while (usedIds.has(id2)) {
|
|
@@ -587,7 +614,7 @@ function parseMarkdown(markdown2) {
|
|
|
587
614
|
id2 = `${baseId}-${n}`;
|
|
588
615
|
}
|
|
589
616
|
usedIds.add(id2);
|
|
590
|
-
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0 });
|
|
617
|
+
result.push({ type: "header", level, text: text2, id: id2, classes: classes2 || void 0, align });
|
|
591
618
|
i++;
|
|
592
619
|
continue;
|
|
593
620
|
}
|
|
@@ -763,29 +790,13 @@ function parseMarkdown(markdown2) {
|
|
|
763
790
|
let tagStartMatch = trimmed.match(/^<([a-zA-Z][\w-]*)/);
|
|
764
791
|
if (tagStartMatch) {
|
|
765
792
|
const tagName = tagStartMatch[1].toLowerCase();
|
|
766
|
-
const voidElements = /* @__PURE__ */ new Set([
|
|
767
|
-
"area",
|
|
768
|
-
"base",
|
|
769
|
-
"br",
|
|
770
|
-
"col",
|
|
771
|
-
"embed",
|
|
772
|
-
"hr",
|
|
773
|
-
"img",
|
|
774
|
-
"input",
|
|
775
|
-
"link",
|
|
776
|
-
"meta",
|
|
777
|
-
"param",
|
|
778
|
-
"source",
|
|
779
|
-
"track",
|
|
780
|
-
"wbr"
|
|
781
|
-
]);
|
|
782
793
|
const remainingText = lines.slice(i).join("\n");
|
|
783
794
|
const openTagRegex = new RegExp(`^\\s*<${tagName}\\b([^>]*?)>`, "i");
|
|
784
795
|
const openTagMatch = remainingText.match(openTagRegex);
|
|
785
796
|
if (openTagMatch) {
|
|
786
797
|
const fullOpenTag = openTagMatch[0];
|
|
787
798
|
const attrs = openTagMatch[1].replace(/\s+/g, " ").trim();
|
|
788
|
-
const isSelfClosing = fullOpenTag.endsWith("/>") ||
|
|
799
|
+
const isSelfClosing = fullOpenTag.endsWith("/>") || VOID_ELEMENTS.has(tagName);
|
|
789
800
|
if (isSelfClosing) {
|
|
790
801
|
const blockText = remainingText.substring(0, openTagMatch.index + fullOpenTag.length);
|
|
791
802
|
const consumedLines = blockText.split("\n").length;
|
|
@@ -1308,11 +1319,77 @@ function parseInlinePart(part) {
|
|
|
1308
1319
|
return document.createTextNode(part);
|
|
1309
1320
|
}
|
|
1310
1321
|
|
|
1322
|
+
// vanilla/utils.ts
|
|
1323
|
+
var THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
1324
|
+
"primary",
|
|
1325
|
+
"secondary",
|
|
1326
|
+
"accent",
|
|
1327
|
+
"neutral",
|
|
1328
|
+
"info",
|
|
1329
|
+
"success",
|
|
1330
|
+
"warning",
|
|
1331
|
+
"error"
|
|
1332
|
+
]);
|
|
1333
|
+
function isThemeToken(color) {
|
|
1334
|
+
return !!color && THEME_TOKENS.has(color);
|
|
1335
|
+
}
|
|
1336
|
+
function isArbitraryColor(value) {
|
|
1337
|
+
if (THEME_TOKENS.has(value)) return false;
|
|
1338
|
+
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
1339
|
+
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
1340
|
+
return false;
|
|
1341
|
+
}
|
|
1342
|
+
function applyBaseProps(el, props) {
|
|
1343
|
+
if (props.class) {
|
|
1344
|
+
el.classList.add(...props.class.split(/\s+/).filter(Boolean));
|
|
1345
|
+
}
|
|
1346
|
+
if (props.style) {
|
|
1347
|
+
const styles = parseCssString(props.style);
|
|
1348
|
+
for (const [key, value] of Object.entries(styles)) {
|
|
1349
|
+
el.style.setProperty(key, String(value));
|
|
1350
|
+
}
|
|
1351
|
+
}
|
|
1352
|
+
}
|
|
1353
|
+
function applyFloatStyle(el, float, width) {
|
|
1354
|
+
if (!float) return;
|
|
1355
|
+
if (float === "left" || float === "right") {
|
|
1356
|
+
el.style.float = float;
|
|
1357
|
+
if (!width) el.style.maxWidth = "50%";
|
|
1358
|
+
el.style.marginInlineStart = float === "right" ? "1rem" : "";
|
|
1359
|
+
el.style.marginInlineEnd = float === "left" ? "1rem" : "";
|
|
1360
|
+
} else if (float === "center") {
|
|
1361
|
+
el.style.marginInline = "auto";
|
|
1362
|
+
}
|
|
1363
|
+
}
|
|
1364
|
+
function applyColor(el, color, classSuffix) {
|
|
1365
|
+
if (!color) return "";
|
|
1366
|
+
if (isThemeToken(color)) {
|
|
1367
|
+
return ` ${classSuffix}--${color}`;
|
|
1368
|
+
}
|
|
1369
|
+
if (isArbitraryColor(color)) {
|
|
1370
|
+
el.style.background = color;
|
|
1371
|
+
el.style.color = "white";
|
|
1372
|
+
}
|
|
1373
|
+
return "";
|
|
1374
|
+
}
|
|
1375
|
+
function openModal(dialog) {
|
|
1376
|
+
if (!dialog.open) {
|
|
1377
|
+
document.body.appendChild(dialog);
|
|
1378
|
+
dialog.showModal();
|
|
1379
|
+
dialog.addEventListener("close", () => dialog.remove(), { once: true });
|
|
1380
|
+
}
|
|
1381
|
+
}
|
|
1382
|
+
var IMG_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1383
|
+
function parseIntProp(value, defaultValue) {
|
|
1384
|
+
if (!value) return defaultValue;
|
|
1385
|
+
const n = parseInt(value, 10);
|
|
1386
|
+
return Number.isNaN(n) ? defaultValue : n;
|
|
1387
|
+
}
|
|
1388
|
+
|
|
1311
1389
|
// vanilla/directives/admonition.ts
|
|
1312
1390
|
var admonitionDirective = ({ directiveType, props, renderSlot }) => {
|
|
1313
1391
|
const el = createAdmonition(directiveType, props.title, props.icon);
|
|
1314
|
-
|
|
1315
|
-
if (props.style) el.setAttribute("style", props.style);
|
|
1392
|
+
applyBaseProps(el, props);
|
|
1316
1393
|
const body = el.querySelector(".nr-admonition__body");
|
|
1317
1394
|
if (body) {
|
|
1318
1395
|
body.appendChild(renderSlot("default"));
|
|
@@ -1328,8 +1405,7 @@ var detailsDirective = ({ props, renderSlot }) => {
|
|
|
1328
1405
|
props.icon,
|
|
1329
1406
|
props.defaultOpen === "true"
|
|
1330
1407
|
);
|
|
1331
|
-
|
|
1332
|
-
if (props.style) el.setAttribute("style", props.style);
|
|
1408
|
+
applyBaseProps(el, props);
|
|
1333
1409
|
const body = el.querySelector(".nr-details__body");
|
|
1334
1410
|
if (body) {
|
|
1335
1411
|
body.appendChild(renderSlot("default"));
|
|
@@ -1342,12 +1418,12 @@ var details_default = detailsDirective;
|
|
|
1342
1418
|
var modalDirective = ({ props, renderSlot }) => {
|
|
1343
1419
|
const label = props.label || props.title || "Open";
|
|
1344
1420
|
const modalTitle = props.title || "Modal";
|
|
1345
|
-
const
|
|
1421
|
+
const align = props.align || "left";
|
|
1346
1422
|
const wrapper = document.createElement("div");
|
|
1347
|
-
wrapper.className = "nr-modal-trigger"
|
|
1423
|
+
wrapper.className = `nr-modal-trigger${align === "center" ? " nr-modal-trigger--center" : align === "right" ? " nr-modal-trigger--right" : ""}`;
|
|
1348
1424
|
const btn = document.createElement("button");
|
|
1349
1425
|
btn.className = `nr-button nr-button--default`;
|
|
1350
|
-
|
|
1426
|
+
applyBaseProps(btn, props);
|
|
1351
1427
|
const icon = props.icon || "open_in_new";
|
|
1352
1428
|
if (icon) btn.appendChild(createIcon(icon));
|
|
1353
1429
|
btn.appendChild(document.createTextNode(label));
|
|
@@ -1359,15 +1435,7 @@ var modalDirective = ({ props, renderSlot }) => {
|
|
|
1359
1435
|
prose.appendChild(renderSlot("default"));
|
|
1360
1436
|
body.appendChild(prose);
|
|
1361
1437
|
}
|
|
1362
|
-
btn.addEventListener("click", () =>
|
|
1363
|
-
if (!dialog.open) {
|
|
1364
|
-
document.body.appendChild(dialog);
|
|
1365
|
-
dialog.showModal();
|
|
1366
|
-
dialog.addEventListener("close", () => {
|
|
1367
|
-
dialog.remove();
|
|
1368
|
-
}, { once: true });
|
|
1369
|
-
}
|
|
1370
|
-
});
|
|
1438
|
+
btn.addEventListener("click", () => openModal(dialog));
|
|
1371
1439
|
wrapper.appendChild(btn);
|
|
1372
1440
|
wrapper.appendChild(dialog);
|
|
1373
1441
|
return wrapper;
|
|
@@ -1377,19 +1445,20 @@ var modal_default = modalDirective;
|
|
|
1377
1445
|
// vanilla/directives/button.ts
|
|
1378
1446
|
var buttonDirective = ({ props, renderSlot }) => {
|
|
1379
1447
|
const url = props.url || props.href || "#";
|
|
1380
|
-
const label = props.label;
|
|
1448
|
+
const label = props.label || props.title;
|
|
1381
1449
|
const icon = props.icon || "near_me";
|
|
1382
1450
|
const target = props.target || "_blank";
|
|
1383
1451
|
const customClass = props.class || "";
|
|
1452
|
+
const align = props.align || "left";
|
|
1384
1453
|
const wrapper = document.createElement("div");
|
|
1385
|
-
wrapper.className = "nr-button-wrap"
|
|
1454
|
+
wrapper.className = `nr-button-wrap${align === "center" ? " nr-button-wrap--center" : align === "right" ? " nr-button-wrap--right" : ""}`;
|
|
1386
1455
|
if (label) {
|
|
1387
1456
|
const a = document.createElement("a");
|
|
1388
1457
|
a.href = url;
|
|
1389
1458
|
a.target = target;
|
|
1390
1459
|
a.rel = "noopener noreferrer";
|
|
1391
1460
|
a.className = "nr-button nr-button--default";
|
|
1392
|
-
|
|
1461
|
+
applyBaseProps(a, props);
|
|
1393
1462
|
a.appendChild(createIcon(icon));
|
|
1394
1463
|
a.appendChild(document.createTextNode(label));
|
|
1395
1464
|
wrapper.appendChild(a);
|
|
@@ -1400,7 +1469,7 @@ var buttonDirective = ({ props, renderSlot }) => {
|
|
|
1400
1469
|
if (links.length > 0) {
|
|
1401
1470
|
links.forEach((link) => {
|
|
1402
1471
|
link.classList.add("nr-button", "nr-button--default");
|
|
1403
|
-
|
|
1472
|
+
applyBaseProps(link, props);
|
|
1404
1473
|
});
|
|
1405
1474
|
wrapper.appendChild(slotContent);
|
|
1406
1475
|
} else {
|
|
@@ -1409,7 +1478,7 @@ var buttonDirective = ({ props, renderSlot }) => {
|
|
|
1409
1478
|
a.target = target;
|
|
1410
1479
|
a.rel = "noopener noreferrer";
|
|
1411
1480
|
a.className = "nr-button nr-button--default";
|
|
1412
|
-
|
|
1481
|
+
applyBaseProps(a, props);
|
|
1413
1482
|
a.appendChild(createIcon(icon));
|
|
1414
1483
|
a.appendChild(slotContent);
|
|
1415
1484
|
wrapper.appendChild(a);
|
|
@@ -1432,12 +1501,9 @@ var cardDirective = ({
|
|
|
1432
1501
|
const { isSingleCard } = options || {};
|
|
1433
1502
|
const isModal = directiveType === "card-m";
|
|
1434
1503
|
const isLink = directiveType === "card-b";
|
|
1435
|
-
const inlineStyles = props.style ? parseCssString(props.style) : {};
|
|
1436
1504
|
const card = document.createElement("div");
|
|
1437
1505
|
card.className = `nr-card${isModal || isLink ? " nr-card--interactive" : ""} ${customClass}`.trim();
|
|
1438
|
-
|
|
1439
|
-
card.style.setProperty(key, String(value));
|
|
1440
|
-
}
|
|
1506
|
+
applyBaseProps(card, props);
|
|
1441
1507
|
if (image) {
|
|
1442
1508
|
const imgWrap = document.createElement("div");
|
|
1443
1509
|
imgWrap.className = `nr-card__image${isSingleCard ? " nr-card__image--tall" : ""}`;
|
|
@@ -1516,13 +1582,7 @@ var cardDirective = ({
|
|
|
1516
1582
|
prose.appendChild(renderSlot("content") || renderSlot("default"));
|
|
1517
1583
|
modalBody.appendChild(prose);
|
|
1518
1584
|
}
|
|
1519
|
-
card.addEventListener("click", () =>
|
|
1520
|
-
if (!dialog.open) {
|
|
1521
|
-
document.body.appendChild(dialog);
|
|
1522
|
-
dialog.showModal();
|
|
1523
|
-
dialog.addEventListener("close", () => dialog.remove(), { once: true });
|
|
1524
|
-
}
|
|
1525
|
-
});
|
|
1585
|
+
card.addEventListener("click", () => openModal(dialog));
|
|
1526
1586
|
const frag = document.createDocumentFragment();
|
|
1527
1587
|
frag.appendChild(card);
|
|
1528
1588
|
frag.appendChild(dialog);
|
|
@@ -1570,8 +1630,8 @@ var slideDirective = ({
|
|
|
1570
1630
|
if (lines.length === 0) {
|
|
1571
1631
|
return document.createDocumentFragment();
|
|
1572
1632
|
}
|
|
1573
|
-
const interval =
|
|
1574
|
-
const speed =
|
|
1633
|
+
const interval = parseIntProp(props.interval, 3e3);
|
|
1634
|
+
const speed = parseIntProp(props.speed, 500);
|
|
1575
1635
|
const rawClass = props.class || "";
|
|
1576
1636
|
const inlineStyle = props.style ? parseCssString(props.style) : {};
|
|
1577
1637
|
const scopeClass = `sld-${++slideCounter}`;
|
|
@@ -1622,10 +1682,11 @@ var slideDirective = ({
|
|
|
1622
1682
|
}
|
|
1623
1683
|
});
|
|
1624
1684
|
if (lines.length > 1) {
|
|
1625
|
-
setInterval(() => {
|
|
1685
|
+
const id = setInterval(() => {
|
|
1626
1686
|
current = (current + 1) % lines.length;
|
|
1627
1687
|
track.style.transform = `translateY(${-current * maxH}px)`;
|
|
1628
1688
|
}, interval);
|
|
1689
|
+
container.dataset.nrIntervalId = String(id);
|
|
1629
1690
|
}
|
|
1630
1691
|
return container;
|
|
1631
1692
|
};
|
|
@@ -1635,8 +1696,7 @@ var slide_default = slideDirective;
|
|
|
1635
1696
|
var keysDirective = ({ props, slots }) => {
|
|
1636
1697
|
const wrap = document.createElement("div");
|
|
1637
1698
|
wrap.className = "nr-keys";
|
|
1638
|
-
|
|
1639
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1699
|
+
applyBaseProps(wrap, props);
|
|
1640
1700
|
const sizeClass = props.size ? ` nr-kbd--${props.size}` : "";
|
|
1641
1701
|
const parts = (slots.default || "").split("+").map((p) => p.trim()).filter(Boolean);
|
|
1642
1702
|
parts.forEach((part, i) => {
|
|
@@ -1660,8 +1720,7 @@ var accordionCounter = 0;
|
|
|
1660
1720
|
var accordionItemDirective = ({ props, renderSlot }) => {
|
|
1661
1721
|
const item = document.createElement("div");
|
|
1662
1722
|
item.className = "nr-accordion__item";
|
|
1663
|
-
|
|
1664
|
-
if (props.style) item.setAttribute("style", props.style);
|
|
1723
|
+
applyBaseProps(item, props);
|
|
1665
1724
|
const input = document.createElement("input");
|
|
1666
1725
|
input.type = "radio";
|
|
1667
1726
|
input.className = "nr-accordion__input";
|
|
@@ -1680,8 +1739,7 @@ var accordionItemDirective = ({ props, renderSlot }) => {
|
|
|
1680
1739
|
var accordionDirective = ({ props, renderSlot }) => {
|
|
1681
1740
|
const wrap = document.createElement("div");
|
|
1682
1741
|
wrap.className = "nr-accordion";
|
|
1683
|
-
|
|
1684
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1742
|
+
applyBaseProps(wrap, props);
|
|
1685
1743
|
wrap.appendChild(renderSlot("default"));
|
|
1686
1744
|
const mode = props.mode === "checkbox" ? "checkbox" : "radio";
|
|
1687
1745
|
const group = `nr-acc-${++accordionCounter}`;
|
|
@@ -1694,7 +1752,6 @@ var accordionDirective = ({ props, renderSlot }) => {
|
|
|
1694
1752
|
var accordion_default = accordionDirective;
|
|
1695
1753
|
|
|
1696
1754
|
// vanilla/directives/carousel.ts
|
|
1697
|
-
var IMG_RE = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1698
1755
|
var carouselDirective = ({ props, slots }) => {
|
|
1699
1756
|
const images = [];
|
|
1700
1757
|
const raw = slots.default || "";
|
|
@@ -1710,19 +1767,9 @@ var carouselDirective = ({ props, slots }) => {
|
|
|
1710
1767
|
wrap.className = "nr-carousel";
|
|
1711
1768
|
wrap.tabIndex = 0;
|
|
1712
1769
|
wrap.setAttribute("aria-label", "Image carousel");
|
|
1713
|
-
|
|
1714
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1770
|
+
applyBaseProps(wrap, props);
|
|
1715
1771
|
if (props.width) wrap.style.width = props.width;
|
|
1716
|
-
|
|
1717
|
-
if (props.float === "left" || props.float === "right") {
|
|
1718
|
-
wrap.style.float = props.float;
|
|
1719
|
-
if (!props.width) wrap.style.maxWidth = "50%";
|
|
1720
|
-
wrap.style.marginInlineStart = props.float === "right" ? "1rem" : "";
|
|
1721
|
-
wrap.style.marginInlineEnd = props.float === "left" ? "1rem" : "";
|
|
1722
|
-
} else if (props.float === "center") {
|
|
1723
|
-
wrap.style.marginInline = "auto";
|
|
1724
|
-
}
|
|
1725
|
-
}
|
|
1772
|
+
applyFloatStyle(wrap, props.float, props.width);
|
|
1726
1773
|
const viewport = document.createElement("div");
|
|
1727
1774
|
viewport.className = "nr-carousel__viewport";
|
|
1728
1775
|
if (props.height) viewport.style.height = props.height;
|
|
@@ -1792,11 +1839,10 @@ var DEFAULT_LABELS = ["days", "hours", "min", "sec"];
|
|
|
1792
1839
|
var countdownDirective = ({ props }) => {
|
|
1793
1840
|
const wrap = document.createElement("div");
|
|
1794
1841
|
wrap.className = "nr-countdown";
|
|
1795
|
-
|
|
1796
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
1842
|
+
applyBaseProps(wrap, props);
|
|
1797
1843
|
const labelParts = (props.labels || "").split("|").map((s) => s.trim());
|
|
1798
1844
|
const labels = DEFAULT_LABELS.map((label, i) => labelParts[i] || label);
|
|
1799
|
-
const digits =
|
|
1845
|
+
const digits = parseIntProp(props.digits, 2);
|
|
1800
1846
|
const targetTime = props.target ? new Date(props.target).getTime() : NaN;
|
|
1801
1847
|
const hasTarget = !Number.isNaN(targetTime);
|
|
1802
1848
|
const blocks = [];
|
|
@@ -1843,13 +1889,15 @@ var countdownDirective = ({ props }) => {
|
|
|
1843
1889
|
blocks.push({ value });
|
|
1844
1890
|
});
|
|
1845
1891
|
render();
|
|
1846
|
-
if (hasTarget)
|
|
1892
|
+
if (hasTarget) {
|
|
1893
|
+
const id = setInterval(render, 1e3);
|
|
1894
|
+
wrap.dataset.nrIntervalId = String(id);
|
|
1895
|
+
}
|
|
1847
1896
|
return wrap;
|
|
1848
1897
|
};
|
|
1849
1898
|
var countdown_default = countdownDirective;
|
|
1850
1899
|
|
|
1851
1900
|
// vanilla/directives/diff.ts
|
|
1852
|
-
var IMG_RE2 = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1853
1901
|
var diffDirective = ({ props, slots }) => {
|
|
1854
1902
|
let before = (props.before || "").split("#")[0].trim();
|
|
1855
1903
|
let after = (props.after || "").split("#")[0].trim();
|
|
@@ -1857,8 +1905,8 @@ var diffDirective = ({ props, slots }) => {
|
|
|
1857
1905
|
const urls = [];
|
|
1858
1906
|
const raw = slots.default || "";
|
|
1859
1907
|
let m;
|
|
1860
|
-
|
|
1861
|
-
while ((m =
|
|
1908
|
+
IMG_RE.lastIndex = 0;
|
|
1909
|
+
while ((m = IMG_RE.exec(raw)) !== null) {
|
|
1862
1910
|
urls.push(m[2].split("#")[0].trim());
|
|
1863
1911
|
}
|
|
1864
1912
|
if (!before && urls.length > 0) before = urls[0];
|
|
@@ -1871,21 +1919,11 @@ var diffDirective = ({ props, slots }) => {
|
|
|
1871
1919
|
figure.className = "nr-diff";
|
|
1872
1920
|
figure.tabIndex = 0;
|
|
1873
1921
|
figure.setAttribute("aria-label", "Image comparison slider");
|
|
1874
|
-
|
|
1875
|
-
if (props.style) figure.setAttribute("style", props.style);
|
|
1922
|
+
applyBaseProps(figure, props);
|
|
1876
1923
|
if (props.aspect) figure.style.aspectRatio = props.aspect;
|
|
1877
1924
|
if (props.height) figure.style.height = props.height;
|
|
1878
1925
|
if (props.width) figure.style.width = props.width;
|
|
1879
|
-
|
|
1880
|
-
if (props.float === "left" || props.float === "right") {
|
|
1881
|
-
figure.style.float = props.float;
|
|
1882
|
-
if (!props.width) figure.style.maxWidth = "50%";
|
|
1883
|
-
figure.style.marginInlineStart = props.float === "right" ? "1rem" : "";
|
|
1884
|
-
figure.style.marginInlineEnd = props.float === "left" ? "1rem" : "";
|
|
1885
|
-
} else if (props.float === "center") {
|
|
1886
|
-
figure.style.marginInline = "auto";
|
|
1887
|
-
}
|
|
1888
|
-
}
|
|
1926
|
+
applyFloatStyle(figure, props.float, props.width);
|
|
1889
1927
|
const beforeItem = document.createElement("div");
|
|
1890
1928
|
beforeItem.className = "nr-diff__item nr-diff__item--before";
|
|
1891
1929
|
beforeItem.setAttribute("role", "img");
|
|
@@ -1948,8 +1986,7 @@ var diff_default = diffDirective;
|
|
|
1948
1986
|
var hover3dDirective = ({ props, renderSlot }) => {
|
|
1949
1987
|
const container = document.createElement("div");
|
|
1950
1988
|
container.className = "nr-hover-3d";
|
|
1951
|
-
|
|
1952
|
-
if (props.style) container.setAttribute("style", props.style);
|
|
1989
|
+
applyBaseProps(container, props);
|
|
1953
1990
|
const stage = document.createElement("div");
|
|
1954
1991
|
stage.className = "nr-hover-3d__stage";
|
|
1955
1992
|
stage.appendChild(renderSlot("default"));
|
|
@@ -1962,14 +1999,13 @@ var hover3dDirective = ({ props, renderSlot }) => {
|
|
|
1962
1999
|
var hover3d_default = hover3dDirective;
|
|
1963
2000
|
|
|
1964
2001
|
// vanilla/directives/hovergallery.ts
|
|
1965
|
-
var IMG_RE3 = /!\[([^\]]*)\]\(([^)]+)\)/g;
|
|
1966
2002
|
var MAX_IMAGES = 10;
|
|
1967
2003
|
var hovergalleryDirective = ({ props, slots }) => {
|
|
1968
2004
|
const images = [];
|
|
1969
2005
|
const raw = slots.default || "";
|
|
1970
2006
|
let m;
|
|
1971
|
-
|
|
1972
|
-
while ((m =
|
|
2007
|
+
IMG_RE.lastIndex = 0;
|
|
2008
|
+
while ((m = IMG_RE.exec(raw)) !== null) {
|
|
1973
2009
|
images.push({ src: m[2].split("#")[0].trim(), alt: m[1].trim() || "gallery image" });
|
|
1974
2010
|
}
|
|
1975
2011
|
if (images.length === 0) {
|
|
@@ -1978,9 +2014,8 @@ var hovergalleryDirective = ({ props, slots }) => {
|
|
|
1978
2014
|
const count = Math.min(images.length, MAX_IMAGES);
|
|
1979
2015
|
const figure = document.createElement("figure");
|
|
1980
2016
|
figure.className = "nr-hover-gallery";
|
|
2017
|
+
applyBaseProps(figure, props);
|
|
1981
2018
|
if (props.aspect) figure.style.aspectRatio = props.aspect;
|
|
1982
|
-
if (props.class) figure.classList.add(...props.class.split(/\s+/).filter(Boolean));
|
|
1983
|
-
if (props.style) figure.setAttribute("style", (figure.getAttribute("style") || "") + ";" + props.style);
|
|
1984
2019
|
const imgEls = [];
|
|
1985
2020
|
for (let i = 0; i < count; i++) {
|
|
1986
2021
|
const el = document.createElement("img");
|
|
@@ -2030,28 +2065,11 @@ var hovergalleryDirective = ({ props, slots }) => {
|
|
|
2030
2065
|
var hovergallery_default = hovergalleryDirective;
|
|
2031
2066
|
|
|
2032
2067
|
// vanilla/directives/chat.ts
|
|
2033
|
-
var CHAT_THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
2034
|
-
"primary",
|
|
2035
|
-
"secondary",
|
|
2036
|
-
"accent",
|
|
2037
|
-
"neutral",
|
|
2038
|
-
"info",
|
|
2039
|
-
"success",
|
|
2040
|
-
"warning",
|
|
2041
|
-
"error"
|
|
2042
|
-
]);
|
|
2043
|
-
function isArbitraryColor(value) {
|
|
2044
|
-
if (CHAT_THEME_TOKENS.has(value)) return false;
|
|
2045
|
-
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
2046
|
-
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
2047
|
-
return false;
|
|
2048
|
-
}
|
|
2049
2068
|
var chatItemDirective = ({ props, renderSlot }) => {
|
|
2050
2069
|
const side = props.side === "end" ? "end" : "start";
|
|
2051
2070
|
const wrap = document.createElement("div");
|
|
2052
2071
|
wrap.className = `nr-chat nr-chat--${side}`;
|
|
2053
|
-
|
|
2054
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
2072
|
+
applyBaseProps(wrap, props);
|
|
2055
2073
|
const header = document.createElement("div");
|
|
2056
2074
|
header.className = "nr-chat__header";
|
|
2057
2075
|
if (props.name) {
|
|
@@ -2076,14 +2094,8 @@ var chatItemDirective = ({ props, renderSlot }) => {
|
|
|
2076
2094
|
avatar.appendChild(img);
|
|
2077
2095
|
wrap.appendChild(avatar);
|
|
2078
2096
|
}
|
|
2079
|
-
const isThemeToken = CHAT_THEME_TOKENS.has(props.color || "");
|
|
2080
|
-
const colorClass = isThemeToken ? ` nr-chat__bubble--${props.color}` : "";
|
|
2081
2097
|
const bubble = document.createElement("div");
|
|
2082
|
-
bubble.className = `nr-chat__bubble${
|
|
2083
|
-
if (props.color && isArbitraryColor(props.color) && !isThemeToken) {
|
|
2084
|
-
bubble.style.background = props.color;
|
|
2085
|
-
bubble.style.color = "white";
|
|
2086
|
-
}
|
|
2098
|
+
bubble.className = `nr-chat__bubble${applyColor(bubble, props.color, "nr-chat__bubble")}`;
|
|
2087
2099
|
bubble.appendChild(renderSlot("default"));
|
|
2088
2100
|
wrap.appendChild(bubble);
|
|
2089
2101
|
if (props.footer) {
|
|
@@ -2097,8 +2109,7 @@ var chatItemDirective = ({ props, renderSlot }) => {
|
|
|
2097
2109
|
var chatDirective = ({ props, renderSlot }) => {
|
|
2098
2110
|
const wrap = document.createElement("div");
|
|
2099
2111
|
wrap.className = "nr-chat";
|
|
2100
|
-
|
|
2101
|
-
if (props.style) wrap.setAttribute("style", props.style);
|
|
2112
|
+
applyBaseProps(wrap, props);
|
|
2102
2113
|
wrap.appendChild(renderSlot("default"));
|
|
2103
2114
|
return wrap;
|
|
2104
2115
|
};
|
|
@@ -2134,8 +2145,7 @@ function bindEventProp(el, eventProp) {
|
|
|
2134
2145
|
var richlistItemDirective = ({ props, renderSlot }) => {
|
|
2135
2146
|
const li = document.createElement("li");
|
|
2136
2147
|
li.className = "nr-richlist__item";
|
|
2137
|
-
|
|
2138
|
-
if (props.style) li.setAttribute("style", props.style);
|
|
2148
|
+
applyBaseProps(li, props);
|
|
2139
2149
|
if (props.image) {
|
|
2140
2150
|
const thumb = document.createElement("div");
|
|
2141
2151
|
thumb.className = "nr-richlist__thumb";
|
|
@@ -2197,36 +2207,20 @@ var richlistItemDirective = ({ props, renderSlot }) => {
|
|
|
2197
2207
|
var richlistDirective = ({ props, renderSlot }) => {
|
|
2198
2208
|
const ul = document.createElement("ul");
|
|
2199
2209
|
ul.className = "nr-richlist";
|
|
2200
|
-
|
|
2201
|
-
if (props.style) ul.setAttribute("style", props.style);
|
|
2210
|
+
applyBaseProps(ul, props);
|
|
2202
2211
|
ul.appendChild(renderSlot("default"));
|
|
2203
2212
|
return ul;
|
|
2204
2213
|
};
|
|
2205
2214
|
var richlist_default = richlistDirective;
|
|
2206
2215
|
|
|
2207
2216
|
// vanilla/directives/stat.ts
|
|
2208
|
-
var STAT_THEME_TOKENS = /* @__PURE__ */ new Set([
|
|
2209
|
-
"primary",
|
|
2210
|
-
"secondary",
|
|
2211
|
-
"info",
|
|
2212
|
-
"success",
|
|
2213
|
-
"warning",
|
|
2214
|
-
"error"
|
|
2215
|
-
]);
|
|
2216
|
-
function isArbitraryColor2(value) {
|
|
2217
|
-
if (STAT_THEME_TOKENS.has(value)) return false;
|
|
2218
|
-
if (/^(#|rgb|hsl|oklch|oklab|lab|lch|color\()/i.test(value)) return true;
|
|
2219
|
-
if (/^[a-zA-Z]+$/.test(value)) return true;
|
|
2220
|
-
return false;
|
|
2221
|
-
}
|
|
2222
2217
|
var statDirective = ({ props }) => {
|
|
2223
|
-
const
|
|
2224
|
-
const colorClass =
|
|
2218
|
+
const statIsThemeToken = isThemeToken(props.color);
|
|
2219
|
+
const colorClass = statIsThemeToken ? ` nr-stat--${props.color}` : "";
|
|
2225
2220
|
const stat = document.createElement("div");
|
|
2226
2221
|
stat.className = `nr-stat${colorClass}`;
|
|
2227
|
-
|
|
2228
|
-
|
|
2229
|
-
const useInlineColor = props.color && isArbitraryColor2(props.color) && !isThemeToken;
|
|
2222
|
+
applyBaseProps(stat, props);
|
|
2223
|
+
const useInlineColor = props.color && isArbitraryColor(props.color) && !statIsThemeToken;
|
|
2230
2224
|
if (props.icon) {
|
|
2231
2225
|
const figure = document.createElement("div");
|
|
2232
2226
|
figure.className = "nr-stat__figure";
|
|
@@ -2319,9 +2313,12 @@ function renderHtmlString(html) {
|
|
|
2319
2313
|
processedContent = processedContent.replace(
|
|
2320
2314
|
/<style(?:\s+[^>]*)?>([\s\S]*?)<\/style>/gi,
|
|
2321
2315
|
(_match, cssContent) => {
|
|
2316
|
+
const trimmed = cssContent.trim();
|
|
2317
|
+
const existing = document.head.querySelector("style[data-nr-global]");
|
|
2318
|
+
if (existing && existing.textContent === trimmed) return "";
|
|
2322
2319
|
const styleEl = document.createElement("style");
|
|
2323
2320
|
styleEl.setAttribute("data-nr-global", "");
|
|
2324
|
-
styleEl.textContent =
|
|
2321
|
+
styleEl.textContent = trimmed;
|
|
2325
2322
|
document.head.appendChild(styleEl);
|
|
2326
2323
|
return "";
|
|
2327
2324
|
}
|
|
@@ -2391,19 +2388,14 @@ function renderElement(element, ctx, allElements) {
|
|
|
2391
2388
|
switch (element.type) {
|
|
2392
2389
|
case "header": {
|
|
2393
2390
|
const tag = `h${element.level}`;
|
|
2394
|
-
let text = element.text;
|
|
2395
|
-
const alignCenter = text.match(/^->\s*(.+?)\s*<-\s*$/);
|
|
2396
|
-
const alignRight = text.match(/^->\s*(.+?)\s*->\s*$/);
|
|
2397
|
-
if (alignCenter) text = alignCenter[1];
|
|
2398
|
-
else if (alignRight) text = alignRight[1];
|
|
2399
2391
|
const h = document.createElement(tag);
|
|
2400
2392
|
h.id = element.id;
|
|
2401
2393
|
let cls = `md-h${element.level}`;
|
|
2402
|
-
if (
|
|
2403
|
-
if (
|
|
2394
|
+
if (element.align === "center") cls += " text-center";
|
|
2395
|
+
else if (element.align === "right") cls += " text-right";
|
|
2404
2396
|
if (element.classes) cls += ` ${element.classes}`;
|
|
2405
2397
|
h.className = cls;
|
|
2406
|
-
h.appendChild(renderInline(text));
|
|
2398
|
+
h.appendChild(renderInline(element.text));
|
|
2407
2399
|
return h;
|
|
2408
2400
|
}
|
|
2409
2401
|
case "paragraph": {
|
|
@@ -2771,7 +2763,7 @@ var guideData = [
|
|
|
2771
2763
|
"title": "Modal",
|
|
2772
2764
|
"icon": "open_in_full",
|
|
2773
2765
|
"order": 2,
|
|
2774
|
-
"md": '# Modal\n\nLa directiva `:::modal` crea un **di\xE1logo modal** con su bot\xF3n de apertura.\n\n## Sintaxis\n\n```md\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n```\n\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n\n## Contenido enriquecido\n\n```md\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n```\n\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `title` | texto | T\xEDtulo del modal |\n| `label` | texto | Texto del bot\xF3n de apertura (
|
|
2766
|
+
"md": '# Modal\n\nLa directiva `:::modal` crea un **di\xE1logo modal** con su bot\xF3n de apertura.\n\n## Sintaxis\n\n```md\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n```\n\n:::modal {title="Confirmar borrado" label="Abrir modal" icon="delete"}\n\xBFSeguro que quieres borrar este documento? Esta acci\xF3n no se puede deshacer.\n\n| Acci\xF3n | Efecto |\n| --- | --- |\n| Aceptar | Borra el documento |\n| Cancelar | No hace nada |\n:::\n\n## Contenido enriquecido\n\n```md\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n```\n\n:::modal {title="Notas de la versi\xF3n" label="Ver novedades" icon="new_releases"}\n**v2.0** \u2014 cambios principales:\n\n- Nuevo componente `:::diff`\n- Gu\xEDa integrada en el editor\n- Especificidad CSS corregida en im\xE1genes\n:::\n\n## Alineaci\xF3n del bot\xF3n\n\nEl bot\xF3n de apertura se alinea a la izquierda por defecto. Usa el prop `align` para cambiar la alineaci\xF3n:\n\n### Centrado\n\n```md\n:::modal {title="Centrado" label="Abrir" icon="open_in_full" align="center"}\nContenido del modal centrado.\n:::\n```\n\n:::modal {title="Centrado" label="Abrir" icon="open_in_full" align="center"}\nContenido del modal centrado.\n:::\n\n### Alineado a la derecha\n\n```md\n:::modal {title="Derecha" label="Abrir" icon="open_in_full" align="right"}\nContenido del modal alineado a la derecha.\n:::\n```\n\n:::modal {title="Derecha" label="Abrir" icon="open_in_full" align="right"}\nContenido del modal alineado a la derecha.\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `title` | texto | T\xEDtulo del modal |\n| `label` (o `title`) | texto | Texto del bot\xF3n de apertura (`title` funciona como alias, default: \xABOpen\xBB) |\n| `icon` | nombre Material | Icono del bot\xF3n (default `open_in_new`) |\n| `align` | `left` / `center` / `right` | Alineaci\xF3n del bot\xF3n de apertura (default `left`) |\n| `class` | texto | Clases CSS adicionales |\n| `style` | CSS | Estilos inline |\n\n## Interacci\xF3n\n\n- **Bot\xF3n**: abre el modal (focus se mueve dentro).\n- **Overlay** o bot\xF3n **\xD7**: cierra.\n- **Esc**: cierra (en desktop).\n- `dialog` nativo \u2192 accesible por defecto, focus trapped y `inert` al fondo.'
|
|
2775
2767
|
},
|
|
2776
2768
|
{
|
|
2777
2769
|
"id": "button",
|
|
@@ -2779,7 +2771,7 @@ var guideData = [
|
|
|
2779
2771
|
"title": "Button",
|
|
2780
2772
|
"icon": "touch_app",
|
|
2781
2773
|
"order": 3,
|
|
2782
|
-
"md": '# Button\n\nLa directiva `:::button` crea un **bot\xF3n con enlace** (se abre en pesta\xF1a nueva por defecto).\n\n## Sintaxis\n\n```md\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n```\n\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n\n## Variante con enlace interno\n\n```md\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n```\n\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n\n## Con contenido markdown\n\nSi el bloque contiene texto/enlaces, se renderizan dentro del bot\xF3n:\n\n```md\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n```\n\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `label` | texto | Texto del bot\xF3n |\n| `url` (o `href`) | URL | Destino del enlace (default `#`) |\n| `icon` | nombre Material | Icono (default `near_me`) |\n| `target` | `_blank` / `_self` / ... | Destino del enlace (default `_blank`) |\n| `class` | texto | Clases CSS adicionales |'
|
|
2774
|
+
"md": '# Button\n\nLa directiva `:::button` crea un **bot\xF3n con enlace** (se abre en pesta\xF1a nueva por defecto).\n\n## Sintaxis\n\n```md\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n```\n\n:::button {label="Documentaci\xF3n" url="https://example.com" icon="menu_book"}\n:::\n\n## Variante con enlace interno\n\n```md\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n```\n\n:::button {label="Ir a la p\xE1gina de notas" url="#admonici\xF3n-nota" icon="sticky_note_2" target="_self"}\n:::\n\n## Con contenido markdown\n\nSi el bloque contiene texto/enlaces, se renderizan dentro del bot\xF3n:\n\n```md\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n```\n\n:::button {label="Descargar" url="https://example.com/download" icon="download"}\nDescarga el **manual** en PDF\n:::\n\n## Alineaci\xF3n\n\nLos botones se alinean a la izquierda por defecto. Usa el prop `align` para cambiar la alineaci\xF3n:\n\n### Centrado\n\n```md\n:::button {label="Centrado" url="https://example.com" icon="center_focus_strong" align="center"}\n:::\n```\n\n:::button {label="Centrado" url="https://example.com" icon="center_focus_strong" align="center"}\n:::\n\n### Alineado a la derecha\n\n```md\n:::button {label="Derecha" url="https://example.com" icon="arrow_forward" align="right"}\n:::\n```\n\n:::button {label="Derecha" url="https://example.com" icon="arrow_forward" align="right"}\n:::\n\n## Props\n\n| Prop | Tipo | Descripci\xF3n |\n| --- | --- | --- |\n| `label` (o `title`) | texto | Texto del bot\xF3n (`title` funciona como alias por compatibilidad) |\n| `url` (o `href`) | URL | Destino del enlace (default `#`) |\n| `icon` | nombre Material | Icono (default `near_me`) |\n| `target` | `_blank` / `_self` / ... | Destino del enlace (default `_blank`) |\n| `align` | `left` / `center` / `right` | Alineaci\xF3n del bot\xF3n (default `left`) |\n| `class` | texto | Clases CSS adicionales |'
|
|
2783
2775
|
},
|
|
2784
2776
|
{
|
|
2785
2777
|
"id": "slide",
|